package org.spring.bse.home.bo;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.spring.bse.home.dao.BseIndiaDAO;
import org.spring.bse.home.model.Stock;

public class BseIndiaBO
{
	BseIndiaDAO bseIndiaDAO = new BseIndiaDAO();

	public String getActiveScripCodes()
	{
		String scripCodeCSV = "";
		List<Integer> scripCodeList = null;
		scripCodeList = bseIndiaDAO.getActiveScripCodes();

		if (scripCodeList != null && !scripCodeList.isEmpty())
		{
			StringBuffer scripCodeBuff = null;
			int LIMIT = 155;
			for (int ind = 0; ind < scripCodeList.size(); ind++)
			{
				if (ind % LIMIT == 0)
				{
					scripCodeBuff = new StringBuffer();
					scripCodeBuff.append(scripCodeList.get(ind));
				}
				else
				{
					scripCodeBuff.append(",").append(scripCodeList.get(ind));
				}
				if (ind % LIMIT == LIMIT - 1 || ind + 1 == scripCodeList.size())
				{
					scripCodeCSV = scripCodeCSV + ";" + scripCodeBuff.toString();
				}
			}
			scripCodeCSV = scripCodeCSV.substring(1);
		}
		String[] csvArr = scripCodeCSV.split(";");
		for (String queryStr : csvArr)
		{
			new HitAsThread("http://localhost:8080/bseIndia/persistGoogleXMLFeed?scripCSV=" + queryStr);
		}

		return scripCodeCSV;
	}

	public String persistGoogleXMLFeed(String queryStr)
	{
		String str = null;

		List<Stock> stkList = getStockListFromGoogle(queryStr);
		long msBefore = System.currentTimeMillis();
		long msCurrent = System.currentTimeMillis();

		while ((str == null) || (str.equals("DB_LOCKED") && msCurrent - msBefore < (1000 * 30)))
		{
			str = bseIndiaDAO.persistGoogleXMLFeed(stkList);
			if (str.equals("DB_LOCKED"))
			{
				try
				{
					Thread.sleep(1000);
				}
				catch (InterruptedException e)
				{
					e.printStackTrace();
				}
			}
			else
			{
				break;
			}
		}

		return str;
	}

	public List<Stock> getAllStocks()
	{
		List<Stock> stockList = bseIndiaDAO.getAllStocks();
		return stockList;
	}
	
	
	private List<Stock> getStockListFromGoogle(String queryStr)
	{
		String strUrl = "http://www.google.com/ig/api?" + queryStr;
		int retryCount = 0;
		List<Stock> stkList = null;
		while (retryCount < 5)
		{
			try
			{
				Document doc;
				int symbol;
				String tmpStr;
				Stock stk = null;
				stkList = new ArrayList<Stock>();

				System.out.println("Reading...");
				doc = Jsoup.connect(strUrl).get();
				for (Element ele : doc.select("finance"))
				{
					// validation
					if (ele.select("market_cap").attr("data").trim().isEmpty() || ele.select("market_cap").attr("data").trim().equals("0"))
						continue;

					stk = new Stock();

					symbol = Integer.parseInt(ele.select("symbol").attr("data"));
					stk.setScripCode(symbol);
					stk.setScripName(ele.select("company").attr("data"));
					tmpStr = ele.select("last").attr("data");
					stk.setCurValue(tmpStr == null || tmpStr.isEmpty() ? 0.0F : Float.parseFloat(tmpStr));
					tmpStr = ele.select("change").attr("data");
					stk.setChgValue(tmpStr == null || tmpStr.isEmpty() ? 0.0F : Float.parseFloat(tmpStr));
					tmpStr = ele.select("perc_change").attr("data");
					stk.setChgPer(tmpStr == null || tmpStr.isEmpty() ? 0.0F : Float.parseFloat(tmpStr));

					stk.setLastTradeTime(frameTS(ele.select("trade_date_utc").attr("data"), ele.select("trade_time_utc").attr("data")));

					tmpStr = ele.select("high").attr("data");
					stk.setDayHigh(tmpStr == null || tmpStr.isEmpty() ? 0.0F : Float.parseFloat(tmpStr));
					tmpStr = ele.select("low").attr("data");
					stk.setDayLow(tmpStr == null || tmpStr.isEmpty() ? 0.0F : Float.parseFloat(tmpStr));
					tmpStr = ele.select("y_close").attr("data");
					stk.setLastClose(tmpStr == null || tmpStr.isEmpty() ? 0.0F : Float.parseFloat(tmpStr));
					tmpStr = ele.select("open").attr("data");
					stk.setLastOpen(tmpStr == null || tmpStr.isEmpty() ? 0.0F : Float.parseFloat(tmpStr));
					tmpStr = ele.select("volume").attr("data");
					stk.setCurVolume(tmpStr == null || tmpStr.isEmpty() ? 0.0D : Double.parseDouble(tmpStr));
					tmpStr = ele.select("market_cap").attr("data");
					stk.setMarketCap(tmpStr == null || tmpStr.isEmpty() ? 0.0D : Double.parseDouble(tmpStr));
					tmpStr = ele.select("trade_timestamp").attr("data");
					stk.setUpdatedAt(tmpStr.contains(" ago") ? tmpStr : "");

					stkList.add(stk);
				}
			}
			catch (Exception e)
			{
				retryCount++;
				System.out.println(e.getMessage());
				continue;
			}
			retryCount = 6;
		}
		return stkList;
	}

	private static Timestamp frameTS(String date, String time)
	{
		Timestamp tradeTS = null;
		int yyyy = 0, mon = 0, dd = 0, hh = 0, mm = 0, ss = 0;

		if ((date != null && date.trim().length() == 8) && (time != null && time.trim().length() == 6))
		{
			yyyy = Integer.parseInt(date.substring(0, 4));
			mon = Integer.parseInt(date.substring(4, 6));
			dd = Integer.parseInt(date.substring(6, 8));

			hh = Integer.parseInt(time.substring(0, 2)) + 5;
			mm = Integer.parseInt(time.substring(2, 4)) + 30;
			hh = (mm >= 60) ? hh + 1 : hh;
			mm = mm % 60;
			ss = Integer.parseInt(time.substring(4, 6));

			Calendar cal = Calendar.getInstance();
			cal.set(yyyy, mon, dd, hh, mm, ss);
			tradeTS = new Timestamp(cal.getTimeInMillis());
		}
		return tradeTS;
	}

	class HitAsThread extends Thread
	{
		private String urlStr = null;

		public void run()
		{
			try
			{
				URLConnection connection;
				connection = new URL(urlStr).openConnection();
				InputStream response = connection.getInputStream();
				response.close();
			}
			catch (MalformedURLException e)
			{
				e.printStackTrace();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}

		public HitAsThread(String urlStr)
		{
			this.urlStr = urlStr;
			this.start();
		}
	}
}
